package com.wfs.myapp.config;

import com.alibaba.fastjson.JSON;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import javax.persistence.EntityManager;
import javax.validation.constraints.NotNull;
import java.util.Map;

/**
 * @author Jason Long
 */
@EnableJpaRepositories(basePackages = {"com.wfs.myapp.repository"})
@Configuration
@Slf4j
public class DefaultDataConfiguration implements ApplicationContextAware, CommandLineRunner {
    private ApplicationContext applicationContext;

    @Bean
    public JPAQueryFactory queryFactory(EntityManager entityManager) {
        return new JPAQueryFactory(entityManager);
    }

    @Override
    public void run(String... args) {
        GenericConversionService genericConversionService = ((GenericConversionService) DefaultConversionService.getSharedInstance());
        Map<String, Object> jpaDtoMaps = applicationContext.getBeansWithAnnotation(JpaDto.class);
        for (Object jpaDto : jpaDtoMaps.values()) {
            log.info("add user defined converter [{}]==>>[{}]", Map.class, jpaDto.getClass());
            Converter convertor = objectMap -> {
                try {
                    String content = JSON.toJSONString(objectMap);
                    return JSON.parseObject(content, jpaDto.getClass());
                } catch (Exception e) {
                    throw new FatalBeanException("JpaDto conversion exception ,class=" + jpaDto.getClass().getName(), e);
                }
            };
            genericConversionService.addConverter(Map.class, jpaDto.getClass(), convertor);
        }
    }

    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}